package cn.stylefeng.guns.modular.business.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.stylefeng.guns.modular.business.comment.YunHeKey;
import cn.stylefeng.guns.modular.business.entity.CyclopediaInfo;
import cn.stylefeng.guns.modular.business.entity.SubDic;
import cn.stylefeng.guns.modular.business.enums.CyclopediaInfoExceptionEnum;
import cn.stylefeng.guns.modular.business.mapper.CyclopediaInfoMapper;
import cn.stylefeng.guns.modular.business.pojo.CyclopediaInfoRequest;
import cn.stylefeng.guns.modular.business.service.CyclopediaInfoService;
import cn.stylefeng.guns.modular.business.service.SubUseBrowseService;
import cn.stylefeng.roses.kernel.auth.api.LoginUserApi;
import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser;
import cn.stylefeng.roses.kernel.db.api.factory.PageFactory;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import cn.stylefeng.roses.kernel.rule.util.HttpServletUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 百科信息表业务实现层
 *
 * @author zhangyaowen
 * @date 2021/11/05 15:32
 */
@Service
public class CyclopediaInfoServiceImpl extends ServiceImpl<CyclopediaInfoMapper, CyclopediaInfo> implements CyclopediaInfoService {

    @Resource
    private SubUseBrowseService subUseBrowseService;
    @Resource
    private LoginUserApi loginUserApi;
    
	@Override
    public void add(CyclopediaInfoRequest cyclopediaInfoRequest) {
        CyclopediaInfo cyclopediaInfo = new CyclopediaInfo();
        BeanUtil.copyProperties(cyclopediaInfoRequest, cyclopediaInfo);
        this.save(cyclopediaInfo);
    }

    @Override
    public void del(CyclopediaInfoRequest cyclopediaInfoRequest) {
        CyclopediaInfo cyclopediaInfo = this.queryCyclopediaInfo(cyclopediaInfoRequest);
        this.removeById(cyclopediaInfo.getId());
    }

    @Override
    public void edit(CyclopediaInfoRequest cyclopediaInfoRequest) {
        CyclopediaInfo cyclopediaInfo = this.queryCyclopediaInfo(cyclopediaInfoRequest);
        BeanUtil.copyProperties(cyclopediaInfoRequest, cyclopediaInfo);
        this.updateById(cyclopediaInfo);
    }

    @Override
    public CyclopediaInfo detail(CyclopediaInfoRequest cyclopediaInfoRequest) {
        return this.queryCyclopediaInfo(cyclopediaInfoRequest);
    }

    @Override
    public PageResult<CyclopediaInfo> findPage(CyclopediaInfoRequest cyclopediaInfoRequest) {
        LambdaQueryWrapper<CyclopediaInfo> wrapper = createWrapper(cyclopediaInfoRequest);
        Page<CyclopediaInfo> sysRolePage = this.page(PageFactory.defaultPage(), wrapper);
        return PageResultFactory.createPageResult(sysRolePage);
    }

    @Override
    public List<CyclopediaInfo> findList(CyclopediaInfoRequest cyclopediaInfoRequest) {
        LambdaQueryWrapper<CyclopediaInfo> wrapper = this.createWrapper(cyclopediaInfoRequest);
        return this.list(wrapper);
    }

    /**
     * 获取信息
     *
     * @author zhangyaowen
     * @date 2021/11/05 15:32
     */
    private CyclopediaInfo queryCyclopediaInfo(CyclopediaInfoRequest cyclopediaInfoRequest) {
        CyclopediaInfo cyclopediaInfo = this.getById(cyclopediaInfoRequest.getId());
        if (ObjectUtil.isEmpty(cyclopediaInfo)) {
            throw new ServiceException(CyclopediaInfoExceptionEnum.CYCLOPEDIAINFO_NOT_EXISTED);
        }
        return cyclopediaInfo;
    }

    /**
     * 创建查询wrapper
     *
     * @author zhangyaowen
     * @date 2021/11/05 15:32
     */
    private LambdaQueryWrapper<CyclopediaInfo> createWrapper(CyclopediaInfoRequest cyclopediaInfoRequest) {
        LambdaQueryWrapper<CyclopediaInfo> queryWrapper = new LambdaQueryWrapper<>();

        Long id = cyclopediaInfoRequest.getId();
        String cycFirst = cyclopediaInfoRequest.getCycFirst();
        String cycSecond = cyclopediaInfoRequest.getCycSecond();
        String cycEntry = cyclopediaInfoRequest.getCycEntry();
        String cycParaphrase = cyclopediaInfoRequest.getCycParaphrase();

        queryWrapper.eq(ObjectUtil.isNotNull(id), CyclopediaInfo::getId, id);
        queryWrapper.like(ObjectUtil.isNotEmpty(cycFirst), CyclopediaInfo::getCycFirst, cycFirst);
        queryWrapper.like(ObjectUtil.isNotEmpty(cycSecond), CyclopediaInfo::getCycSecond, cycSecond);
        queryWrapper.like(ObjectUtil.isNotEmpty(cycEntry), CyclopediaInfo::getCycEntry, cycEntry);
        queryWrapper.like(ObjectUtil.isNotEmpty(cycParaphrase), CyclopediaInfo::getCycParaphrase, cycParaphrase);

        return queryWrapper;
    }


    @Override
    public List<String> findFirst() {
        LambdaQueryWrapper<CyclopediaInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(CyclopediaInfo::getCycFirst);
        List<CyclopediaInfo>  cyclopediaInfoList = this.list(queryWrapper);
        List<String> projectList2 = cyclopediaInfoList.stream().map(CyclopediaInfo::getCycFirst).distinct().collect(Collectors.toList());
        return projectList2;
    }

    @Override
    public List<String> findSecond(String cycFirst) {
        LambdaQueryWrapper<CyclopediaInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(ObjectUtil.isNotEmpty(cycFirst), CyclopediaInfo::getCycFirst, cycFirst);
        queryWrapper.select(CyclopediaInfo::getCycSecond,CyclopediaInfo::getCycFirst);
        List<CyclopediaInfo>  cyclopediaInfoList = this.list(queryWrapper);
        if(cyclopediaInfoList.get(0).getCycSecond() == null){
//            LambdaQueryWrapper<CyclopediaInfo> wrapper = new LambdaQueryWrapper<>();
//            wrapper.like(ObjectUtil.isNotEmpty(cycFirst), CyclopediaInfo::getCycFirst, cycFirst);
//            wrapper.select(CyclopediaInfo::getCycEntry);
//            List<CyclopediaInfo>  cyclopediaInfoList1 = this.list(queryWrapper);
//            List<String> list = cyclopediaInfoList1.stream().map(CyclopediaInfo::getCycSecond).distinct().collect(Collectors.toList());
            List<String> list1 = new ArrayList<>();
            return list1;
        }else{
            List<String> list = cyclopediaInfoList.stream().map(CyclopediaInfo::getCycSecond).distinct().collect(Collectors.toList());
            return list;
        }

    }

    @Override
    public List<Map<String,Object>> findEntry(String cycFirst,String cycSecond) {
        List<Map<String,Object>> mapList = new ArrayList<>();
        LambdaQueryWrapper<CyclopediaInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(ObjectUtil.isNotEmpty(cycFirst), CyclopediaInfo::getCycFirst, cycFirst);
        queryWrapper.like(ObjectUtil.isNotEmpty(cycSecond), CyclopediaInfo::getCycSecond, cycSecond);
        queryWrapper.select(CyclopediaInfo::getCycEntry,CyclopediaInfo::getCycFirst,CyclopediaInfo::getCycFirst,CyclopediaInfo::getId);
        List<CyclopediaInfo>  cyclopediaInfoList = this.list(queryWrapper);
//        List<String> cyclopediaList = cyclopediaInfoList.stream().map(CyclopediaInfo::getCycFirst).distinct().collect(Collectors.toList());
        for(CyclopediaInfo cyclopediaInfo : cyclopediaInfoList){
            Map<String, Object> map = new HashMap<String, Object>();
//            map = JSONObject.parseObject(JSONObject.toJSONString(projectScience), Map.class);
            byte[] key = YunHeKey.PASSWORD.getBytes(StandardCharsets.UTF_8);
            SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);
            String jmid = YunHeKey.YHBK+cyclopediaInfo.getCycFirst()+"-"+cyclopediaInfo.getCycSecond()+"-"+cyclopediaInfo.getCycEntry()+"-"+cyclopediaInfo.getId();
            String encryptHex = aes.encryptHex(jmid);
            map.put("id",encryptHex);
            map.put("title",cyclopediaInfo.getCycEntry());
            mapList.add(map);
        }
        return mapList;
    }

    @Override
    public List<Map<String,Object>> findAllList(List<SubDic> riverList, List<SubDic> townList, String[] times, String name) {
        LambdaQueryWrapper<CyclopediaInfo> wrapper = createWrapperByCyc(riverList,townList,times,name);
        List<CyclopediaInfo>  list = this.list(wrapper);
        List<Map<String,Object>> mapList=new ArrayList<>();
        for(CyclopediaInfo cyclopediaInfo:list) {
            Map<String, Object> map = new HashMap<String, Object>();

            map.put("title", cyclopediaInfo.getCycEntry());
            map.put("historyDating","");
            map.put("theCommon","");
            map.put("from",YunHeKey.BK);
            map.put("createTime", DateUtil.format(cyclopediaInfo.getCreateTime(), "yyyy-MM-dd"));
            map.put("type",YunHeKey.YHBK);
            byte[] key = YunHeKey.PASSWORD.getBytes(StandardCharsets.UTF_8);
            SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);

            String jmid = YunHeKey.YHBK+cyclopediaInfo.getCycFirst()+"-"+cyclopediaInfo.getCycSecond()+"-"+cyclopediaInfo.getCycEntry()+"-"+cyclopediaInfo.getId();
            String encryptHex = aes.encryptHex(jmid);
            map.put("id",encryptHex);
            map.put("cycFirst", cyclopediaInfo.getCycFirst());
            map.put("cycSecond",cyclopediaInfo.getCycSecond());
            map.put("cycEntry",cyclopediaInfo.getCycEntry());
            mapList.add(map);
        }
        return mapList;
    }

    /**
     * 创建查询wrapper
     *
     * @author zhangyaowen
     * @date 2021/08/30 10:17
     */
    private LambdaQueryWrapper<CyclopediaInfo> createWrapperByCyc(List<SubDic> riverList, List<SubDic> townList, String[] times, String name) {
        LambdaQueryWrapper<CyclopediaInfo> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.and(i-> i.like(ObjectUtil.isNotNull(name), CyclopediaInfo::getCycEntry, name).or());
        if( !riverList.isEmpty()) {
            queryWrapper.and(wrapper -> {
                for (int i = 0; i < riverList.size(); i++) {
                    String dicAname = riverList.get(i).getDicAname();
                    wrapper.like(ObjectUtil.isNotEmpty(dicAname), CyclopediaInfo::getXgRiver, dicAname);
                    if (i != riverList.size() - 1) {
                        wrapper.or();
                    }
                }
            });
        }
        if( !townList.isEmpty()) {
            queryWrapper.and(wrapper -> {
                for (int i = 0; i < townList.size(); i++) {
                    String dicZname = townList.get(i).getDicZname();
                    wrapper.like(ObjectUtil.isNotEmpty(dicZname), CyclopediaInfo::getXgTown, dicZname);
                    if (i != townList.size() - 1) {
                        wrapper.or();
                    }
                }
            });
        }
        return queryWrapper;
    }

    @Override
    public Map<String, Object> toReview(String jmId) {
        byte[] key =YunHeKey.PASSWORD.getBytes(StandardCharsets.UTF_8);
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);
        String decryptStr = aes.decryptStr(jmId, CharsetUtil.CHARSET_UTF_8);
        //获取ID字符串YHSJ后面真实的的id
        String value = StrUtil.subAfter(decryptStr,YunHeKey.YHBK,false);
        HttpServletRequest request = HttpServletUtil.getRequest();
        Long userid;
        if (ObjectUtil.isNotNull(request)) {
            LoginUser loginUser = loginUserApi.getLoginUser();
            userid = loginUser.getUserId();
        } else {
            throw new ServiceException(CyclopediaInfoExceptionEnum.REQUEST_EMPTY);
        }
        LambdaQueryWrapper<CyclopediaInfo> queryWrapper = new LambdaQueryWrapper<>();
        if ("".equals(value)) {
            Map<String, Object> mapLists = new HashMap<>();
            return mapLists;
        }

        String [] strings =StrUtil.splitToArray(value, "-");

        if(strings.length>=4) {
            queryWrapper.eq(ObjectUtil.isNotEmpty(strings[0]), CyclopediaInfo::getCycFirst, strings[0]);
            if(!"null".equals(strings[1])) {
                queryWrapper.eq(ObjectUtil.isNotEmpty(strings[1]), CyclopediaInfo::getCycSecond, strings[1]);
            }
            queryWrapper.eq(ObjectUtil.isNotEmpty(strings[2]), CyclopediaInfo::getCycEntry, strings[2]);
            Long id = Long.parseLong(strings[3]);
            queryWrapper.eq(ObjectUtil.isNotEmpty(id), CyclopediaInfo::getId, id);
        }
        List<CyclopediaInfo> CyclopediaInfoList = this.list(queryWrapper);


        List<Map<String, Object>> mapList = new ArrayList<>();
        for (CyclopediaInfo CyclopediaInfo : CyclopediaInfoList) {

            Map<String, Object> map = new HashMap<String, Object>();
            map = JSONObject.parseObject(JSONObject.toJSONString(CyclopediaInfo), Map.class);

            // 获取类的属性
            Field[] declaredFields = CyclopediaInfo.class.getDeclaredFields();
            List<Map<String, Object>> mplist = new ArrayList<>();
            // 遍历属性，获取属性上ApiModelProperty的值，属性的名，存入Properties
            if (declaredFields.length != 0) {
//                String title = "";
                int i = 1;
                Map<String, Object> p = new HashMap<String, Object>();
                for (Field field : declaredFields) {

                    Map<String, Object> mp = new HashMap<String, Object>();
                    if (field.getAnnotation(ApiModelProperty.class) != null) {
                        //获取注解属性
                        ApiModelProperty aa = field.getAnnotation(ApiModelProperty.class);
                        // key和value可根据需求存
                        // 这存的key为注解的值，value为类属性名

                        if ("cycEntry".equals(field.getName()) || "cycParaphrase".equals(field.getName())  ) {
                            if ("cycEntry".equals(field.getName()) ) {
                                p.put("title", map.get(field.getName()));
                            }
                            else {
                                p.put(field.getName(), map.get(field.getName()));
                            }
                        }else{
                            mp.put("key", aa.value());
                            mp.put("value", map.get(field.getName()));
                            if (i != 1) {
                                mplist.add(mp);
                            }
                        }
                    }
                    i++;
                }
                p.put("list", mplist);
                if (i != 1) {
                    mapList.add(p);
                }
            }
        }
        if(userid != 0l && userid != -1l) {
            subUseBrowseService.saveBrowse(YunHeKey.BK,mapList.get(0).get("title").toString(),userid,request);
        }
        return mapList.get(0);
    }
}